from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.paginator import Paginator
from django.http import HttpResponseRedirect, JsonResponse, HttpResponse
from django.shortcuts import render, get_object_or_404, redirect
import requests
import os
import random
import pandas as pd
from django.db.models import Avg, Count, Q
from django.utils import timezone
from datetime import timedelta
import base64

from .decorators import cold_boot
from .forms import RatingForm, CommentForm, ReplyForm, LoginForm
from .models import Music, UserProfile, Rating, Comment, PlayHistory
from .recommend import build_recommend
from .subscribe import build_genre_ids, build_languages
from django.views.decorators.http import require_POST
from django.views.decorators.csrf import csrf_exempt
from .utils import generate_captcha

# 当前播放
current_play = None
# 当前推荐
current_recommend = []


# 首页
def home(request):
    # 检查用户是否已登录
    if not request.user.is_authenticated:
        # 未登录则重定向到登录页面
        return HttpResponseRedirect('/sign_in')
    # 已登录则显示音乐列表
    return all(request)


@login_required(login_url='/sign_in')
@cold_boot
def all(request):
    page_number = request.GET.get('page', 1)
    queryset = Music.objects.all().order_by('id')  # 添加默认排序
    paginator = Paginator(queryset, 10)  # 分页
    musics = paginator.page(page_number)
    context = {
        'musics': musics,
        'user_likes': [],
        'user_dislikes': []
    }
    # 如果登录的首页
    if request.user.is_authenticated:
        user_profile = UserProfile.objects.filter(user=request.user)
        if user_profile.exists():
            user_profile = user_profile.first()  # 用户信息
            context['user_likes'] = user_profile.likes.all()  # 获取用户喜欢或不喜欢的数据
            context['user_dislikes'] = user_profile.dislikes.all()
    return render(request, 'list.html', context)


# 注册
def sign_up(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user_captcha = request.POST.get('captcha', '').upper()  # 获取并转换为大写
        
        # 获取存储在会话中的验证码
        stored_captcha = request.session.get('captcha_code', '')
        
        # 验证验证码
        if not stored_captcha or user_captcha != stored_captcha:
            messages.error(request, '验证码错误，请重新输入！')
            # 生成新的验证码
            code, _ = generate_captcha()
            request.session['captcha_code'] = code
            return render(request, 'sign_up.html')
        
        if User.objects.filter(username=username).exists():
            messages.error(request, '该用户已存在！')
            # 生成新的验证码
            code, _ = generate_captcha()
            request.session['captcha_code'] = code
        else:
            user_obj = User.objects.create_user(username=username, password=password)
            UserProfile.objects.create(user=user_obj)
            messages.success(request, '注册成功！')
            # 清除验证码
            if 'captcha_code' in request.session:
                del request.session['captcha_code']
            return HttpResponseRedirect('/sign_in')
    
    # 确保有验证码
    if 'captcha_code' not in request.session:
        code, _ = generate_captcha()
        request.session['captcha_code'] = code
        
    return render(request, 'sign_up.html')


# 生成验证码图片
def captcha_image(request):
    # 生成验证码并存入session
    code, image_base64 = generate_captcha()
    # 将验证码存储在session中，以便后续验证
    request.session['captcha_code'] = code
    # 设置30分钟的过期时间
    request.session.set_expiry(1800)
    
    # 从Base64字符串中提取图像数据
    # 格式为: "data:image/png;base64,图像数据"
    image_data = image_base64.split(',')[1]
    decoded_image = base64.b64decode(image_data)
    
    # 返回图片内容
    return HttpResponse(decoded_image, content_type='image/png')


# 登录
def sign_in(request):
    # 如果用户已经登录，直接跳转到首页
    if request.user.is_authenticated:
        return HttpResponseRedirect('/')
    
    form = LoginForm()
    
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            user_captcha = form.cleaned_data['captcha'].upper()  # 转换为大写进行比较
            
            # 获取存储在会话中的验证码
            stored_captcha = request.session.get('captcha_code', '')
            
            # 验证验证码
            if not stored_captcha or user_captcha != stored_captcha:
                messages.error(request, '验证码错误，请重新输入！')
                # 生成新的验证码
                code, _ = generate_captcha()
                request.session['captcha_code'] = code
            else:
                # 验证码正确，继续进行用户认证
                user = authenticate(request, username=username, password=password)
                if user is not None:
                    login(request, user=user)
                    messages.success(request, '登录成功')
                    # 清除验证码
                    if 'captcha_code' in request.session:
                        del request.session['captcha_code']
                    return HttpResponseRedirect('/')
                else:
                    messages.error(request, '用户名或密码错误！')
                    # 生成新的验证码
                    code, _ = generate_captcha()
                    request.session['captcha_code'] = code
    
    # 确保有验证码
    if 'captcha_code' not in request.session:
        code, _ = generate_captcha()
        request.session['captcha_code'] = code
    
    return render(request, 'sign_in.html', {'form': form})


# 退出登录
@login_required(login_url='/sign_in')
def user_logout(request):
    logout(request)
    messages.info(request, '退出登录')
    return HttpResponseRedirect('/sign_in')


@login_required(login_url='/sign_in')
@cold_boot
def recommend(request):
    page_number = request.GET.get('page', 1)

    # -------------------- 推荐 --------------------------
    recommend_set = build_recommend(request, request.user)  # 获取推荐的数据
    # -------------------- 推荐 --------------------------

    paginator = Paginator(recommend_set, 10)  # 分页
    musics = paginator.page(page_number)  # 推荐的音乐
    context = {
        'musics': musics,
        'user_likes': [],
        'user_dislikes': []
    }
    user_profile = UserProfile.objects.filter(user=request.user)
    if user_profile.exists():
        user_profile = user_profile.first()
        context['user_likes'] = user_profile.likes.all()
        context['user_dislikes'] = user_profile.dislikes.all()
    return render(request, 'list.html', context)


# 用户添加喜欢
@login_required(login_url='/sign_in')
def like(request, pk: int):
    user_obj = UserProfile.objects.get(user=request.user)
    music_obj = get_object_or_404(Music.objects.all(), pk=pk)  # 通过id查找歌曲信息
    user_obj.likes.add(music_obj)  # 添加喜欢
    user_obj.dislikes.remove(music_obj)  # 删除不喜欢
    messages.add_message(request, messages.INFO, '已经添加到我喜欢')
    redirect_url = request.GET.get('from', '/')
    if 'action' in request.GET:
        redirect_url += f'&action={request.GET["action"]}'
    return HttpResponseRedirect(redirect_url)


# 用户添加不喜欢
@login_required(login_url='/sign_in')
def dislike(request, pk: int):
    user_obj = UserProfile.objects.get(user=request.user)
    music_obj = get_object_or_404(Music.objects.all(), pk=pk)  # 通过id查找歌曲信息
    user_obj.dislikes.add(music_obj)  # 添加到不喜欢
    user_obj.likes.remove(music_obj)  # 删除喜欢
    messages.add_message(request, messages.INFO, '已经添加到我不喜欢')
    redirect_url = request.GET.get('from', '/')
    if 'action' in request.GET:
        redirect_url += f'&action={request.GET["action"]}'
    return HttpResponseRedirect(redirect_url)


# 播放歌曲
@login_required(login_url='/sign_in')
def play(request, pk: int = 0):
    if pk > 0:  # 存在id
        music_obj = Music.objects.filter(pk=pk)
        if music_obj.exists():
            music = music_obj.first()
            
            # 记录播放历史
            PlayHistory.objects.create(user=request.user, music=music)
            
            return render(request, 'play.html', context={
                'music': music
            })
    
    # 如果没有指定音乐或者音乐不存在，显示错误
    messages.error(request, '当前没有正在播放的音乐')
    return HttpResponseRedirect('/')


# 用户信息
@login_required(login_url='/sign_in')
def user_center(request):
    user_profile = UserProfile.objects.filter(user=request.user)
    if user_profile.exists():
        profile_obj: UserProfile = user_profile.first()
    else:
        messages.error(request, '找不到用户资料，请重新登录')
        logout(request)
        return HttpResponseRedirect('/sign_in')
    # 添加个人信息
    if request.method == 'POST':
        genres = request.POST.getlist('genres', '')
        languages = request.POST.getlist('languages', '')
        profile_obj.first_run = False
        if len(genres) > 0:
            profile_obj.genre_subscribe = ','.join(genres)
            profile_obj.save()
            messages.success(request, '修改流派订阅成功！')
        elif not profile_obj.first_run:
            profile_obj.genre_subscribe = ''
            profile_obj.save()
            messages.success(request, '修改流派订阅成功！')
        if len(languages) > 0:
            profile_obj.language_subscribe = ','.join(languages)
            profile_obj.save()
            messages.success(request, '修改语言订阅成功！')
        elif not profile_obj.first_run:
            profile_obj.language_subscribe = ''
            profile_obj.save()
            messages.success(request, '修改语言订阅成功！')
    context = {
        'user_likes': profile_obj.likes.all(),
        'user_dislikes': profile_obj.dislikes.all(),
        'genres': build_genre_ids(),
        'languages': build_languages(),
        'genre_subscribe': profile_obj.genre_subscribe.split(','),
        'language_subscribe': []
    }
    # 去除空字符
    for lang in profile_obj.language_subscribe.split(','):
        lang = lang.strip()
        context['language_subscribe'].append(lang)
    return render(request, 'user.html', context=context)


# 搜索歌曲
@login_required(login_url='/sign_in')
def search(request):
    if 'keyword' not in request.GET:
        messages.error(request, '请输入搜索关键词')
        return HttpResponseRedirect('/')
    keyword = request.GET.get('keyword')
    action = request.GET.get('action')
    # 两种方式搜索
    musics = []
    if action == 'song_name':
        musics = Music.objects.filter(song_name__contains=keyword)
    if action == 'artist_name':
        musics = Music.objects.filter(artist_name__contains=keyword)
    messages.info(request, f'搜索关键词：{keyword}，找到 {len(musics)} 首音乐')
    context = {
        'musics': musics,
        'user_likes': [],
        'user_dislikes': []
    }
    user_profile = UserProfile.objects.filter(user=request.user)
    if user_profile.exists():
        user_profile = user_profile.first()
        context['user_likes'] = user_profile.likes.all()
        context['user_dislikes'] = user_profile.dislikes.all()
    return render(request, 'list.html', context)


# 测试音乐URL是否可访问
@login_required(login_url='/sign_in')
def test_music_url(request, pk):
    if not request.user.is_staff:
        return JsonResponse({'status': 'error', 'message': '仅管理员可使用此功能'})
    
    try:
        music = Music.objects.get(pk=pk)
        url = music.url
        
        # 测试URL是否可访问
        try:
            response = requests.head(url, timeout=5)
            if response.status_code == 200:
                return JsonResponse({'status': 'success', 'message': 'URL可访问'})
            else:
                return JsonResponse({'status': 'error', 'message': f'URL返回状态码: {response.status_code}'})
        except requests.exceptions.RequestException as e:
            return JsonResponse({'status': 'error', 'message': f'URL不可访问: {str(e)}'})
    except Music.DoesNotExist:
        return JsonResponse({'status': 'error', 'message': '音乐不存在'})


# 音乐详情页，包含评分和评论
@login_required(login_url='/sign_in')
def music_detail(request, pk):
    music = get_object_or_404(Music, pk=pk)
    
    # 记录播放历史
    PlayHistory.objects.create(user=request.user, music=music)
    
    # 获取用户评分
    user_rating = None
    if request.user.is_authenticated:
        user_rating = Rating.objects.filter(user=request.user, music=music).first()
    
    # 获取评论
    comments = Comment.objects.filter(music=music).select_related('user').prefetch_related('replies')
    
    # 表单
    comment_form = CommentForm()
    reply_form = ReplyForm()
    rating_form = RatingForm(instance=user_rating) if user_rating else RatingForm()
    
    # 获取用户喜欢和不喜欢的音乐
    user_likes = []
    user_dislikes = []
    if request.user.is_authenticated:
        user_profile = UserProfile.objects.filter(user=request.user).first()
        if user_profile:
            user_likes = user_profile.likes.all()
            user_dislikes = user_profile.dislikes.all()
    
    context = {
        'music': music,
        'user_rating': user_rating,
        'rating_form': rating_form,
        'comment_form': comment_form,
        'reply_form': reply_form,
        'comments': comments,
        'user_likes': user_likes,
        'user_dislikes': user_dislikes,
    }
    
    return render(request, 'music_detail.html', context)


# 提交评分
@login_required(login_url='/sign_in')
def rate_music(request, pk):
    music = get_object_or_404(Music, pk=pk)
    
    if request.method == 'POST':
        # 获取用户现有评分或创建新的
        rating_instance = Rating.objects.filter(user=request.user, music=music).first()
        
        # 使用表单处理提交的数据
        form = RatingForm(request.POST, instance=rating_instance)
        if form.is_valid():
            rating = form.save(commit=False)
            rating.user = request.user
            rating.music = music
            rating.save()
            
            # 更新音乐的平均评分
            music.update_average_rating()
            
            if rating_instance:
                messages.success(request, '评分已更新！')
            else:
                messages.success(request, '评分成功！')
        else:
            messages.error(request, '评分必须是1到5之间的整数')
    
    return redirect('music_detail', pk=pk)


# 添加评论
@login_required(login_url='/sign_in')
def add_comment(request, pk):
    music = get_object_or_404(Music, pk=pk)
    
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.user = request.user
            comment.music = music
            comment.save()
            messages.success(request, '评论发表成功！')
        else:
            messages.error(request, '评论内容不能为空！')
    
    return redirect('music_detail', pk=pk)


# 回复评论
@login_required(login_url='/sign_in')
def reply_comment(request, comment_id):
    parent_comment = get_object_or_404(Comment, pk=comment_id)
    
    if request.method == 'POST':
        form = ReplyForm(request.POST)
        if form.is_valid():
            reply = form.save(commit=False)
            reply.user = request.user
            reply.music = parent_comment.music
            reply.parent = parent_comment
            reply.save()
            messages.success(request, '回复发表成功！')
        else:
            messages.error(request, '回复内容不能为空！')
    
    return redirect('music_detail', pk=parent_comment.music.pk)


# 用户播放历史
@login_required(login_url='/sign_in')
def play_history(request):
    # 获取当前用户的播放历史记录
    histories = PlayHistory.objects.filter(user=request.user).select_related('music').order_by('-played_at')
    
    # 分页处理
    page_number = request.GET.get('page', 1)
    paginator = Paginator(histories, 10)  # 每页显示10条记录
    page_histories = paginator.page(page_number)
    
    # 获取用户喜欢和不喜欢的音乐列表（用于在页面中显示状态）
    user_profile = UserProfile.objects.filter(user=request.user).first()
    user_likes = []
    user_dislikes = []
    if user_profile:
        user_likes = user_profile.likes.all()
        user_dislikes = user_profile.dislikes.all()
    
    context = {
        'histories': page_histories,
        'user_likes': user_likes,
        'user_dislikes': user_dislikes,
    }
    
    return render(request, 'play_history.html', context)
